var levelup = require('levelup');
var leveldown = require('leveldown')
const fs = require('fs-extra')
const path = require('path')


const { getLevelDbPath, mkdir } = require('./fileUtil')

// TODO 需要处理异常退出后被锁的情况
var db = levelup(leveldown(mkdir(getLevelDbPath())));

async function put(key, value) {
    let data = get(key)
    if (data == null) {
        data = {
            _gmtModified: Date.now(),
            _gmtCreate: Date.now(),
            _data: value,
            _key: key
        }
    } else {
        data = { ...data, _data: value, _gmtModified: Date.now() }
    }

    await db.put(key, JSON.stringify(data))
}

async function get(key) {
    try {
        var retData = await db.get(key)
        return JSON.parse(retData)
    }
    catch (e) {
        return null
    }

}

function del(key, callback) {
    if (key) {
        db.del(key, function (error) {
            callback(error);
        })
    } else {
        callback('no key');
    }
}

function batch(arr, callback) {
    if (Array.isArray(arr)) {
        var batchList = [];
        arr.forEach(item)
        {
            var listMember = {};
            if (item.hasOwnProperty('type')) {
                listMember.type = item.type;
            }
            if (item.hasOwnProperty('key')) {
                listMember.key = item.key;
            }
            if (item.hasOwnProperty('value')) {
                listMember.value = item.value;
            }
            if (listMember.hasOwnProperty('type') && listMember.hasOwnProperty('key') && listMember.hasOwnProperty('value')) {
                batchList.push(listMember);
            }
        }
        if (batchList && batchList.length > 0) {
            db.batch(batchList, function (error) {
                callback(error, batchList);
            })
        } else {
            callback('array Membre format error');
        }
    } else {
        callback('not array');
    }
}

function find(find, callback) {
    var option = { keys: true, values: true, revers: false, limit: 20, fillCache: true };
    if (!find)
        return callback('nothing', null);
    else {
        if (find.prefix) {
            option.start = find.prefix;
            option.end = find.prefix.substring(0, find.prefix.length - 1)
                + String.fromCharCode(find.prefix[find.prefix.length - 1].charCodeAt() + 1);
        }

        if (find.limit)
            option.limit = find.limit;

        db.createReadStream(option).on('data', function (data) {
            data && callback(data.key, data.value);
        }).on('error', function (err) {
        }).on('close', function () {
        }).on('end', function () {
            return callback(null, Date.now());
        });
    }
}

exports.put = put;
exports.get = get;
exports.del = del;
exports.find = find;
exports.batch = batch;